﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.ExtendedReflection.Monitoring;
using Microsoft.ExtendedReflection.Metadata;
using System.Diagnostics;


namespace DUCover
{
    static class TracingExitCodes
    {
        public const int InvalidArguments = -1;
        public const int UnexpectedException = -2;
    }

    class Program
    {
        [LoaderOptimization(LoaderOptimization.MultiDomainHost)]
        static int Main(string[] args)
        {
            Console.WriteLine("Tracing: A .NET program tracer demo application");
            Console.WriteLine("Copyright (c) Microsoft Corporation. All rights reserved.");
            Console.WriteLine("(c) Microsoft Corporation. All rights reserved.");
            Console.WriteLine();
            Console.WriteLine("usage: sample.tracing.exe <application to trace>");
            Console.WriteLine();

            if (args == null || args.Length != 1)
                return TracingExitCodes.InvalidArguments;

            // set up the environment variables for the instrumented process
            var userAssembly = Metadata<Tracer>.Assembly;
            var userType = Metadata<Tracer>.Type;
            var startInfo = new ProcessStartInfo(args[0], null);
            startInfo.UseShellExecute = false;
            ControllerSetUp.SetMonitoringEnvironmentVariables(
                startInfo.EnvironmentVariables,
                MonitorInstrumentationFlags.EnterLeaveMethod |
                MonitorInstrumentationFlags.UnwindMethod |
                MonitorInstrumentationFlags.MethodArguments |
                MonitorInstrumentationFlags.MethodReturnArguments,
                false,
                userAssembly.Location,
                userType.FullName,
                null, // substitutions assemblies
                null, // types to monitor
                null, // types to exclude to monitor
                null, // namespaces to monitor
                null, // namespace to exclude to monitor
                new string[] { "*" }, // assemblies to monitor
                new string[] { 
                    Metadata<Object>.Assembly.ShortName,
                    Metadata<_ThreadContext>.Assembly.ShortName,
                    userAssembly.ShortName,
                    "NLog"}, //assemblies to ignore
                null, // types to project
                null, null, null,
                null, // log file name
                false, // crash on failure
                null, // target clr version
                true, // protect all .cctors
                false, // disable mscorlib supressions
                ProfilerInteraction.Fail // allow loading external profiler
                );

            try
            {
                using (var process = Process.Start(startInfo))
                {
                    process.WaitForExit();
                    return process.ExitCode;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                return TracingExitCodes.UnexpectedException;
            }
        }
    }
}
